package config

import (
	"fmt"
	"github.com/spf13/viper"
	"os"
	"parse-template/src/internal"
	utils2 "parse-template/src/utils"
	"regexp"
	"strings"
)

func getEnvOrPanic(env string) string {
	res := os.Getenv(env)
	if len(env) == 0 {
		panic("Mandatory env variable not found:" + env)
	}
	return res
}

// 解析目标值配置文件
func ParseTemplateValueConfig(context *ApplicationContext) map[string]interface{} {
	internal.InitSysVariable()

	ConfigKeyCache = make(map[string]string)
	result := map[string]interface{}{}

	for key, value := range internal.SysVariable {
		// 将系统变量添加到缓存中，用于替换yaml文件中的${path_root}等系统内置变量
		ConfigKeyCache[key] = value
		// 将系统变量添加到结果中，用于替换模板中的系统内置变量 {{.path_root}}等等
		result[key] = value
	}

	// 遍历全部值对象
	files, _ := utils2.WalkDir(`value` + string(os.PathSeparator))
	files = competitionCurrentEnvYaml(context, files)
	applicationConfig := getApplicationConfig()
	result = utils2.MergeMap(applicationConfig, result)

	saveConfigKeyCache(ConfigKeyCache, files)
	for _, filePath := range files {
		data := map[string]interface{}{}
		viper.New()
		viper.SetConfigType("yaml")
		viper.SetConfigFile(filePath)
		err := viper.ReadInConfig()
		if err != nil {
			fmt.Println(err.Error())
		}
		// 从前面告知的配置中加载配置文件并合并到之前
		//utils.CheckErr(viper.MergeInConfig())
		for _, k := range viper.AllKeys() {
			value := viper.GetString(k)
			if len(value) <= 0 {
				continue
			}
			tmp := value
			reg := regexp.MustCompile(`\$\{([^}]*)\}`)
			for {
				if !reg.MatchString(tmp) {
					break
				}
				for _, regValue := range reg.FindAllString(tmp, -1) {
					// fmt.Println("regexp", regValue)
					if strings.HasPrefix(regValue, "${") && strings.HasSuffix(regValue, "}") {
						// 首先从环境变量中获取变量值
						parserValue := strings.TrimSuffix(strings.TrimPrefix(regValue, "${"), "}")
						envValue := getEnvOrPanic(parserValue)
						if len(envValue) == 0 {
							envValue = ConfigKeyCache[parserValue]
						}
						tmp = strings.ReplaceAll(tmp, regValue, envValue)
					}
				}

			}
			viper.Set(k, tmp)
		}

		utils2.CheckErr(viper.Unmarshal(&data))
		result = utils2.MergeMap(data, result)
	}
	return result
}

// 将配置文件key保存到缓存中
func saveConfigKeyCache(keyCache map[string]string, files []string) {
	for _, filePath := range files {
		viper.New()
		viper.SetConfigType("yaml")
		viper.SetConfigFile(filePath)
		err := viper.ReadInConfig()
		if err != nil {
			fmt.Println(err.Error())
		}
		// 从前面告知的配置中加载配置文件并合并到之前
		//utils.CheckErr(viper.MergeInConfig())
		for _, k := range viper.AllKeys() {
			value := viper.GetString(k)
			ConfigKeyCache[k] = value
		}
	}

	viper.New()
	viper.SetConfigType("yaml")
	viper.SetConfigFile("application.yaml")

	err := viper.ReadInConfig()
	if err != nil {
		fmt.Println(err.Error())
	}
	for _, k := range viper.AllKeys() {
		value := viper.GetString(k)
		ConfigKeyCache[k] = value
	}
}

// 赛选中当前环境的yaml文件
func competitionCurrentEnvYaml(context *ApplicationContext, files []string) []string {
	env := context.Config.App.Env
	var result = []string{}
	for _, file := range files {
		if strings.HasSuffix(file, env+".yaml") {
			result = append(result, file)
		}
	}
	return result
}

func getApplicationConfig() map[string]interface{} {
	data := map[string]interface{}{}
	viper.New()
	viper.SetConfigType("yaml")
	viper.SetConfigFile("application.yaml")

	err := viper.ReadInConfig()
	if err != nil {
		fmt.Println(err.Error())
	}
	// data := map[string]interface{}{}
	err = viper.Unmarshal(&data)
	if err != nil {
		fmt.Println(err.Error())
		panic(err.Error())
	}
	return data
}

// 解析应用配置文件
func ParseApplicationConfig(context *ApplicationContext) {
	viper.New()
	viper.SetConfigType("yaml")
	viper.SetConfigFile("application.yaml")

	err := viper.ReadInConfig()
	if err != nil {
		fmt.Println(err.Error())
	}
	var _config *ApplicationConfig
	// data := map[string]interface{}{}
	err = viper.Unmarshal(&_config)
	if err != nil {
		fmt.Println(err.Error())
		panic(err.Error())
	}
	context.Config = _config
}
